package com.rq.viewtestapplication;

import android.graphics.Point;
import android.view.View;

public class FeaturePoint {
    public static FeaturePoint generatePoint(View v) {
        return new FeaturePoint(v);
    }


    private FeaturePoint(View v) {
        if (v != null) {
            for (int i = 0; i < 3; i++) {
                for (int j = 0; j < 3; j++) {
                    int x = j == 0 ? v.getLeft() : j == 1 ? (v.getLeft() + v.getRight()) / 2 : v.getRight();
                    int y = i == 0 ? v.getTop() : i == 1 ? (v.getTop() + v.getBottom()) / 2 : v.getBottom();
                    point[i][j] = new Point(x, y);
                }
            }
        }
    }

    /**
     * @return 获取临近角落点
     */
    public Point getClosedConnerPoint(Point calc) {
        double dis = Double.MAX_VALUE;
        Point res = null;
        for (int i = 0; i < point.length; i++) {
            for (int k = 0; k < point[i].length; k++) {
                if (i == 1 || k == 1) continue;
                if (dis > disInPoints(calc, point[i][k])) {
                    dis = disInPoints(calc, point[i][k]);
                    res = point[i][k];
                }
            }
        }
        return res;
    }

    public Point getClosedCenterPoint(Point calc) {
        double dis = Double.MAX_VALUE;
        Point res = null;
        for (int i = 0; i < point.length; i++) {
            for (int k = 0; k < point[i].length; k++) {
                if (i != 1 && k != 1) continue;
                if (dis > disInPoints(calc, point[i][k])) {
                    dis = disInPoints(calc, point[i][k]);
                    res = point[i][k];
                }
            }
        }
        return res;
    }

    /**
     * 0,0      0,1     0,2
     * 1,0      1,1     1,2
     * 2,0      2,1     2,2
     */
    Point[][] point = new Point[3][3];

    /**
     * 接近点位置
     *
     * @param p2
     * @param thresholdOfCloseDot
     * @return 5           -   中心重叠
     * 7/9/1/3     -   左上/右上/左下/右下
     * 8/6/2/4     -   上/右/下/左
     */
    public int closeTo(Point p2, float thresholdOfCloseDot) {
        int res = -1;
        LOG.e("FeaturePoint", "closeTo:" + p2.x + "," + p2.y);
        LOG.e("FeaturePoint", "closeTo:" + toString());
        if (disInPoints(point[1][1], p2) <= thresholdOfCloseDot) res = 5;
        if (disInPoints(point[0][0], p2) <= thresholdOfCloseDot) res = 7;
        if (disInPoints(point[0][2], p2) <= thresholdOfCloseDot) res = 9;
        if (disInPoints(point[2][0], p2) <= thresholdOfCloseDot) res = 1;
        if (disInPoints(point[2][2], p2) <= thresholdOfCloseDot) res = 3;
        if (disInPoints(point[0][1], p2) <= thresholdOfCloseDot) res = 8;
        if (disInPoints(point[1][2], p2) <= thresholdOfCloseDot) res = 6;
        if (disInPoints(point[2][1], p2) <= thresholdOfCloseDot) res = 2;
        if (disInPoints(point[1][0], p2) <= thresholdOfCloseDot) res = 4;
        return res;
    }

    /**
     * 是否有重叠/覆盖
     *
     * @param p2
     * @return 5           -   中心重叠
     * 7/9/1/3     -   左上/右上/左下/右下
     * 8/6/2/4     -   上/右/下/左
     */
    public int closeTo(FeaturePoint p2) {
        if (point[1][1].x == p2.point[1][1].x && point[1][1].y == p2.point[1][1].y) return 5;
        if (point[2][2].x < p2.point[0][0].x && point[2][2].y < p2.point[0][0].y) return 7;
        if (point[2][0].x > p2.point[0][2].x && point[2][0].y < p2.point[0][2].y) return 9;
        if (point[0][2].x < p2.point[2][0].x && point[0][2].y > p2.point[2][0].y) return 1;
        if (point[0][0].x > p2.point[2][2].x && point[0][0].y > p2.point[2][2].y) return 3;
        if (point[2][0].x > p2.point[0][0].x && point[2][2].x > p2.point[0][2].y && point[2][1].y < p2.point[0][1].y)
            return 8;
        if (point[0][0].y > p2.point[0][2].y && point[2][0].y < p2.point[2][2].y && point[1][0].y < p2.point[1][2].x)
            return 6;
        if (point[0][0].x > p2.point[0][0].x && point[2][2].x < p2.point[2][2].y && point[0][1].y > p2.point[2][1].y)
            return 2;
        if (point[0][0].y > p2.point[0][0].y && point[2][2].y < p2.point[2][0].y && point[1][2].x < p2.point[1][0].x)
            return 4;
        return 0;
    }

    /**
     * @param p1
     * @param p2
     * @return 两个图形临近特征点的标注
     */
    public static int[] getClosePoint(FeaturePoint p1, FeaturePoint p2) {
        int startX = 0, startY = 0, endX = 0, endY = 0;
        double dis = Integer.MAX_VALUE;
        for (int x1 = 0; x1 < 3; x1++) {
            for (int y1 = 0; y1 < 3; y1++) {
                for (int x2 = 0; x2 < 3; x2++) {
                    for (int y2 = 0; y2 < 3; y2++) {
                        if (dis > disInPoints(p1.point[x1][y1], p2.point[x2][y2])) {
                            dis = disInPoints(p1.point[x1][y1], p2.point[x2][y2]);
                            startX = p1.point[x1][y1].x;
                            startY = p1.point[x1][y1].y;
                            endX = p2.point[x2][y2].x;
                            endY = p2.point[x2][y2].y;
                        }
                    }
                }
            }
        }
        return new int[]{startX, startY, endX, endY};
    }

    /**
     * @param p1
     * @param p2
     * @return 两个图形临近中点的直线标注
     */
    public static int[] getCloseCenterPoint(FeaturePoint p1, FeaturePoint p2) {
        int startX = 0, startY = 0, endX = 0, endY = 0;
        double dis = Integer.MAX_VALUE;
        for (int x1 = 0; x1 < 3; x1++) {
            for (int y1 = 0; y1 < 3; y1++) {
                if (x1 != 1 && y1 != 1) continue;
                for (int x2 = 0; x2 < 3; x2++) {
                    for (int y2 = 0; y2 < 3; y2++) {
                        if (x2 != 1 && y2 != 1) continue;
                        if (dis > disInPoints(p1.point[x1][y1], p2.point[x2][y2])) {
                            dis = disInPoints(p1.point[x1][y1], p2.point[x2][y2]);
                            startX = p1.point[x1][y1].x;
                            startY = p1.point[x1][y1].y;
                            endX = p2.point[x2][y2].x;
                            endY = p2.point[x2][y2].y;
                        }
                    }
                }
            }
        }
        return new int[]{startX, startY, endX, endY};
    }

    private static double disInPoints(Point p1, Point p2) {
        double deltaX = p2.x - p1.x;
        double deltaY = p2.y - p1.y;
        return Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < point.length; i++) {
            for (int k = 0; k < point[i].length; k++) {
                sb.append(point[i][k].x + "," + point[i][k].y);
                sb.append("\t\t");
            }
            sb.append("\n");
        }
        return "FeaturePoint{" +
                "point=\n" + sb.toString() +
                "\n}";
    }

    public boolean closeSide(float x, float y, float dis) {
        return Math.abs(point[0][0].x - x) < dis && (y > point[0][0].y && y < point[2][0].y)
                || Math.abs(point[2][2].x - x) < dis && (y > point[0][2].y && y < point[2][2].y)
                || Math.abs(point[0][0].y - y) < dis && (x > point[0][0].x && x < point[0][2].x)
                || Math.abs(point[2][2].y - y) < dis && (x > point[2][0].x && x < point[2][2].x);
    }

    public int closeSideTag(float x, float y, float dis) {
        return Math.abs(point[0][0].x - x) < dis && (y > point[0][0].y && y < point[2][0].y) ? 4
                : Math.abs(point[2][2].x - x) < dis && (y > point[0][2].y && y < point[2][2].y) ? 6
                : Math.abs(point[0][0].y - y) < dis && (x > point[0][0].x && x < point[0][2].x) ? 8
                : Math.abs(point[2][2].y - y) < dis && (x > point[2][0].x && x < point[2][2].x) ? 2
                : 0;
    }
}
